package cn.netjava.robo3d;

import java.awt.Font;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;

import cn.netjava.robo3d.device.Atlas;
import cn.netjava.robo3d.device.Bullet;
import cn.netjava.robo3d.device.ChaserCam;
import cn.netjava.robo3d.device.ControlDesk;
import cn.netjava.robo3d.test.Robot1;
import cn.netjava.robo3d.test.Test;

import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.input.AbsoluteMouse;
import com.jme.input.ChaseCamera;
import com.jme.input.KeyBindingManager;
import com.jme.input.thirdperson.ThirdPersonMouseLook;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Arrow;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jmex.font3d.Font3D;
import com.jmex.font3d.Text3D;
import com.jmex.terrain.TerrainBlock;

public class Scene extends Node {


	private WarCar player;                          //主角
	private List<TankInformation> alltanksinfo;       //所有坦克属性
	private Sky skynode;
	private SceneLight light;
	private DisplaySystem display;                    //显示器
	private Input input;
	private DashBoard dash;
	private Camera cam;
	private ChaseCamera chaser;
	private ChaserCam   mychaser;  //我自己的追踪摄像机
    private List<Bullet> bullets;
    private List<RoboTank> robotlist;                  //机器人坦克队列
    private TerrainBlock tb;                           //地形
    private Text3D cross1 ;                                  //准星
    private Text3D cross2 ;
    private Text3D cross3 ;
    private Atlas atlas; //地图
    private boolean showatlas=true;
	private AbsoluteMouse mouse;//鼠标
	private ControlDesk controldesk;//游戏控制桌面
	private float feildwide=20;//框框的宽度
	private float feildheight=4f;//框框的高度
	private float feildfar=20;  //框框的距离
	private Sphere sphere1;
	private Sphere sphere2;
	private Sphere sphere3;
	private Sphere sphere4;
	private Sphere movesphere;
	private Vector3f movesphereloc;  //炮筒对着这个打，狠狠的打！！

    private int robotnum=2;                           //机器人坦克个数
    private RandomAccessFile rf;

	///////////////////////////调试箭头
//	private Arrow carnormlarrow=new Arrow("carnormalarrow",2,0.03f); //车体法线
//	private Arrow ternormlarrow=new Arrow("ternormalarrow",4,0.03f);  //地面法线
//	private Arrow leftarrow=new Arrow("leftarrow",2,0.03f);                   //左向法线
//	private Arrow cardirectionarrow=new Arrow("cardirectionarrow",2,0.03f);//车体指示
	private Arrow gundirectionarrow=new Arrow("gundirectionarrow",2,0.08f);
	///////////////////////////

	public Scene(Input input,Camera cam){
		this.cam=cam;
		this.input=input;
		this.display=DisplaySystem.getDisplaySystem();
		createmouse();  //载入鼠标
	    this.setName("scene");
	    alltanksinfo=new ArrayList();
	    Calendar   cal   =   new   GregorianCalendar();
	    //   Get   the   components   of   the   time
        int   hour24   =   cal.get(Calendar.HOUR_OF_DAY);           //   0..23
        int   min   =   cal.get(Calendar.MINUTE);                           //   0..59
        int   year   =   cal.get(Calendar.YEAR);                           //   2002
        int   month   =   cal.get(Calendar.MONTH);                       //   0=Jan,   1=Feb,   ...
        int   day   =   cal.get(Calendar.DAY_OF_MONTH);
        String date="日期:  "+year+"年 "+month+"月 "+day+"日 ---"+hour24+"时 "+min+" 分";
        String rootpath=System.getProperty("user.dir");
//        File initlog=new File(rootpath+"/src/cn/netjava/robo3d/test/initlog.txt");

	    long time1=System.currentTimeMillis();    //毫秒
	    player=new WarCar();         //创建主角

		player.reinit(input);
		String inittxt=date+"   :  初始化主角用时"+(System.currentTimeMillis()-time1)+" /ms\r\n";
        this.attachChild(player);
        try {
		    rf=new RandomAccessFile(rootpath+"/src/cn/netjava/robo3d/test/initlog.txt","rw");
			rf.seek(rf.length());
			rf.write(inittxt.getBytes());
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// the chase cam
 	    //chaser=getChaser(cam,player);  //摄像机只管主玩家
 	    //试试我自己的追踪摄像机
 	    mychaser=new ChaserCam(cam,player);

        Font3D font = new Font3D(new Font("Arial", Font.PLAIN, 24), 0.2f, true, true, true);
		cross1 = font.createText(".", 2.0f, 0);     //瞄星
		cross2 = font.createText(".", 2.0f, 0);     //瞄星
		cross3 = font.createText(".", 2.0f, 0);
		cross1.setLocalScale(new Vector3f(1,1,0.1f).mult(2f));
		cross2.setLocalScale(new Vector3f(1,1,0.1f).mult(1f));
		cross3.setLocalScale(new Vector3f(1,1,0.1f).mult(0.5f));
        this.attachChild(cross1);
        this.attachChild(cross2);
        this.attachChild(cross3);

		robotlist=new ArrayList();      //创建机器坦克队列
		long testtime1=System.currentTimeMillis();
        for(int i=0;i<robotnum;i++){
        	String name="robot-"+i;
            RoboTank tank=new Robot1();
            tank.setName(name);
            tank.reinit(input);
            Vector3f loc=new Vector3f(70+80*(float)Math.random(),0f,70+80*(float)Math.random());
            tank.setLocalTranslation(loc);
        	this.attachChild(tank);
            robotlist.add(tank);
        }
        long testtime2=System.currentTimeMillis();
        inittxt=date+"   :  初始机器坦克用时"+(testtime2-testtime1)+" /ms\r\n";
        try {
			rf.seek(rf.length());
			rf.write(inittxt.getBytes());
			rf.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        //初始化载入天空
		skynode=new Sky();
		this.attachChild(skynode);
		//保存所有坦克信息
		alltanksinfo.add(player.getinfo());
        for(int i=0;i<robotnum;i++){
        	RoboTank temp2tank=robotlist.get(i);
        	alltanksinfo.add(temp2tank.getinfo());
        }
        //给每辆坦克加入其它所有坦克信息
        player.addallothertanksinfo(alltanksinfo);
        for(int i=0;i<robotnum;i++){
     	   robotlist.get(i).addallothertanksinfo(alltanksinfo);
        }
        //创建地图
        atlas=new Atlas(input,alltanksinfo);
        this.attachChild(atlas);
        //创建导航控制器桌面,引用主角坦克，以便控制
        controldesk=new ControlDesk(input,player);
        this.attachChild(controldesk);

		//创建坦克控制线程
		Thread tcar=new Thread(player);
		tcar.start();
        for(int i=0;i<robotnum;i++){
        	System.out.println("新建 "+i+" 线程");
        	Thread Ttank=new Thread(robotlist.get(i));
        	Ttank.start();
        }



		//加入调试箭头
//		this.attachChild(ternormlarrow);
//		this.attachChild(cardirectionarrow);
//		this.attachChild(leftarrow);
//		this.attachChild(carnormlarrow);
		this.attachChild(gundirectionarrow);
//		this.setModelBound(new BoundingBox());
		this.updateWorldBound();

		sphere1=new Sphere("sphere1",10,10,0.4f);
		sphere2=new Sphere("sphere2",10,10,0.3f);
		sphere3=new Sphere("sphere3",10,10,0.3f);
		sphere4=new Sphere("sphere4",10,10,0.3f);
		movesphere=new Sphere("movesphere",10,10,0.2f);
//        this.attachChild(sphere1);
//        this.attachChild(sphere2);
//        this.attachChild(sphere3);
//        this.attachChild(sphere4);
//        this.attachChild(movesphere);

		//照亮世界
	     lightworld();
	}

	//得到主角
	public RoboTank getCar() {
		return player;
	}

	//创建鼠标mouse
	private void createmouse(){

		mouse=new AbsoluteMouse("mouse",display.getWidth(),display.getHeight());
		TextureState ts=display.getRenderer().createTextureState();
        URL cursorLoc = Test.class.getClassLoader().getResource(
        "cn/netjava/robo3d/images/cursor1.png" );
        Texture t = TextureManager.loadTexture( cursorLoc, Texture.MinificationFilter.NearestNeighborNoMipMaps,
                Texture.MagnificationFilter.Bilinear, Image.Format.GuessNoCompression, 1, true );
        ts.setTexture( t );
        mouse.setRenderState(ts);
        mouse.registerWithInputHandler(input);
        mouse.setCullHint(Spatial.CullHint.Never);
     // Make the mouse's background blend with what's already there
        BlendState as = display.getRenderer().createBlendState();
        as.setBlendEnabled( true );
        as.setSourceFunction( BlendState.SourceFunction.SourceAlpha );
        as.setDestinationFunction( BlendState.DestinationFunction.OneMinusSourceAlpha );
        as.setTestEnabled( true );
        as.setTestFunction( BlendState.TestFunction.GreaterThan );
        mouse.setRenderState(as);
        //mouse.setSpeed(1.3f);


        this.attachChild(mouse);

	}

	private ChaseCamera getChaser(Camera cam,Spatial car) {
        Vector3f targetOffset = new Vector3f();
//        targetOffset.y = ((BoundingBox) car.getWorldBound()).yExtent * 1.5f;
        targetOffset.y =car.getLocalTranslation().y+1.5f;
        HashMap<String, Object> props = new HashMap<String, Object>();
        props.put(ThirdPersonMouseLook.PROP_MAXROLLOUT, "3");
        props.put(ThirdPersonMouseLook.PROP_MINROLLOUT, "9");
        props.put(ThirdPersonMouseLook.PROP_MAXASCENT, ""+45 * FastMath.DEG_TO_RAD);
        props.put(ChaseCamera.PROP_INITIALSPHERECOORDS, new Vector3f(15, 20, 10 * FastMath.DEG_TO_RAD));
        props.put(ChaseCamera.PROP_TARGETOFFSET, targetOffset);
        ChaseCamera chaser = new ChaseCamera(cam, car, props);
//        ChaseCamera chaser = new ChaseCamera(cam, car);
        chaser.removeAllActions();
        chaser.setMaxDistance(8);
        chaser.setMinDistance(2);
        return chaser;
    }

	public SceneLight getLight() {
		return light;
	}


	public DashBoard getpanel(){
		return dash;
	}

	public Sky getSky() {
		return skynode;
	}

	private void lightworld(){
		light=new SceneLight();
	    LightState lightState = display.getRenderer().createLightState();
	    lightState.setEnabled(true);
	    lightState.detachAll();
	    lightState.attach(light);
	    this.setRenderState(lightState);
	}

	public void setCar(WarCar player) {
		this.player = player;
	}
	public void setLight(SceneLight light) {
		this.light = light;
	}

	public void setSky(Sky skynode) {
		this.skynode = skynode;
	}

    /**
	 * 刷新场景
	 * @param time
	 */
	private float theta1=0; //框框与右向量的夹角
	public void updatescene(float time){
		tb=(TerrainBlock)this.getChild("tb");
        //update the keyboard input (move the player around)
        input.update(time);

        //是否显示小地图
		if(KeyBindingManager.getKeyBindingManager().isValidCommand("showatlas",
				false)){
			showatlas=!showatlas;
			controldesk.setShowatlas(showatlas);
		}
		showatlas=controldesk.isShowatlas();
		if(showatlas){
			if(!this.hasChild(atlas)){
				this.attachChild(atlas);
			}
			atlas.update();
		}else{
			if(this.hasChild(atlas)){
			    this.detachChild(atlas);
			}
		}


        if(player.getViewmode()==WarCar.chase)
        {
//           chaser.update(time);
        	mychaser.update(time);
        }
        //we want to keep the skybox around our eyes, so move it with
        //the camera
		skynode.setLocalTranslation(cam.getLocation());


        if(player.getViewmode()==WarCar.scope){
        	Vector3f scopeorigin=new Vector3f();     //瞄准模式原点
        	scopeorigin.setX(player.getLocalTranslation().x);
        	scopeorigin.setY(player.getLocalTranslation().y+0.30f);
        	scopeorigin.setZ(player.getLocalTranslation().z);
        	scopeorigin.subtractLocal(player.getgundirection().mult(-0.4f));
        	cam.setLocation(scopeorigin);
        	cam.lookAt(scopeorigin.add(player.getgundirection()), new Vector3f(0,1,0));
        	cam.update();

        }
        //切换观看模式
		if(KeyBindingManager.getKeyBindingManager().isValidCommand("changemode",
				false)){
			System.out.println("即将切换观看模式");
			if(player.getViewmode()==WarCar.chase)
			{
				player.setViewmode(WarCar.scope);
			}else{
				player.setViewmode(WarCar.chase);
			}
		}

		//切换是否显示鼠标图标
		if(controldesk.isShowcursor()){
			mouse.setCullHint(Spatial.CullHint.Never);
		}else{
			mouse.setCullHint(Spatial.CullHint.Always);
		}
		if(KeyBindingManager.getKeyBindingManager().isValidCommand(
				"showcursor", true)){
//			System.out.println("按了O键");
			controldesk.setShowcursor(true);
		}
		//System.out.println("鼠标的位置："+mouse.getLocalTranslation());
//
//		  Vector3f store=new Vector3f();
//          mouse.localToWorld(mouse.getCenter(), store);
//          System.out.println("mouse's center in world:"+store);

		controldesk.update();

		Vector3f sphere1loc=new Vector3f();
		Vector3f sphere2loc=new Vector3f();
		Vector3f sphere3loc=new Vector3f();
		Vector3f sphere4loc=new Vector3f();
		movesphereloc=new Vector3f();
		Vector3f farvec=new Vector3f();
		Vector3f rightvec=new Vector3f();
		Vector3f upvec=new Vector3f(0,1,0);
		Vector3f camdir=new Vector3f();
		Vector3f camright=new Vector3f();
		Vector3f camloc=new Vector3f();

		camloc=cam.getLocation();
		camdir=cam.getDirection().clone().normalize();
		camright=camdir.cross(cam.getUp());
		camright.normalizeLocal();
		farvec=camdir.mult(feildfar);
		rightvec=camright.mult(feildwide);
		upvec=upvec.mult(feildheight);
		sphere1loc=camloc.add(farvec.add(rightvec.mult(-0.5f)));
		sphere2loc=sphere1loc.add(upvec);     //sphere2是原点了
		sphere3loc=sphere2loc.add(rightvec);
		sphere4loc=sphere3loc.add(upvec.mult(-1));
//		movesphereloc=camloc.add(farvec.add(upvec.mult(0.5f)));
		sphere1.setLocalTranslation(sphere1loc);
		sphere2.setLocalTranslation(sphere2loc);
		sphere3.setLocalTranslation(sphere3loc);
		sphere4.setLocalTranslation(sphere4loc);
		//System.out.println(" 鼠标在屏幕的位置："+controldesk.getMouseloc());
		float mouseX=controldesk.getMouseloc().x;
		float mouseY=controldesk.getMouseloc().y;
		//映射到框框内，先要缩放一下
		float scaleX=mouseX/display.getWidth();
		float scaleY=mouseY/display.getHeight();
		Vector3f vecX=rightvec.mult(scaleX);
		Vector3f vecY=upvec.mult(-scaleY);
		movesphereloc=sphere2loc.add(vecX).add(vecY);

		movesphere.setLocalTranslation(movesphereloc);
		//调整炮筒的方位
		//原先的炮筒方向Y不变
		float gunY=player.getgundirection().y;
		Vector3f gundirection2=new Vector3f();
		gundirection2=movesphereloc.subtract(player.getLocalTranslation());
		gundirection2.y=gunY;
		gundirection2.normalizeLocal();
		if(player.getViewmode()==WarCar.chase){
		    player.setgundirection(gundirection2);
		}

		//System.out.println("dddd:"+player.getLocalTranslation());

        //给主角放入子弹///////////////////////////////////////////////////////////////
        for(int i=0;i<player.getbullets().size();i++){
              Bullet bullet=(Bullet)player.getbullets().get(i);
	          if(bullet.islive()&&(!bullet.getinstall())){//新激活子弹并且没有安装
	        	this.attachChild((Bullet)(bullet));
	        	bullet.setinstall(true);    //安装
	            }
	          if((!bullet.islive())&&bullet.getinstall()){  //死子弹并且已经安装
	        	 this.detachChild(bullet);
                 bullet.setinstall(false);   //卸载
	          }
          }
        Vector3f crosstrans=player.getLocalTranslation().add(player.getgundirection().mult(40f));
		cross1.setLocalTranslation(crosstrans);
		crosstrans=player.getLocalTranslation().add(player.getgundirection().mult(20f));
		cross2.setLocalTranslation(crosstrans);
		crosstrans=player.getLocalTranslation().add(player.getgundirection().mult(10f));
		cross3.setLocalTranslation(crosstrans);
        player.update(time, tb);
        ////////////////////////////////////////////////////////////////////

        ////给机器人放入子弹////////////////////////////////////////
        for(int j=0;j<robotnum;j++){
        	RoboTank robottank=robotlist.get(j);
            for(int i=0;i<robottank.getbullets().size();i++){
                Bullet bullet=(Bullet)robottank.getbullets().get(i);
  	          if(bullet.islive()&&(!bullet.getinstall())){//新激活子弹并且没有安装
  	        	this.attachChild((Bullet)(bullet));
  	        	bullet.setinstall(true);    //安装
  	            }
  	          if((!bullet.islive())&&bullet.getinstall()){  //死子弹并且已经安装
  	        	 this.detachChild(bullet);
                   bullet.setinstall(false);   //卸载
  	          }
            }
            robottank.update(time, tb);
        }
        ///////////////////////////////////////////////////////////////////

        //更新箭头
//       ternormlarrow.rotateUpTo(player.getNormal());
//       ternormlarrow.setLocalTranslation(player.getLocalTranslation());
//       cardirectionarrow.rotateUpTo(player.getCardirection());
//       cardirectionarrow.setLocalTranslation(player.getLocalTranslation());
//       leftarrow.rotateUpTo(player.getLeftdirection());
//       leftarrow.setLocalTranslation(player.getLocalTranslation());
//       carnormlarrow.rotateUpTo(player.getLeftdirection().cross(player.getCardirection()).normalize());
//       carnormlarrow.setLocalTranslation(player.getLocalTranslation());
       gundirectionarrow.rotateUpTo(player.getgundirection());
       Vector3f temdir1=player.getLocalTranslation();
       Vector3f temdir2=new Vector3f(temdir1);
       temdir2.y=temdir1.y+0.4f;
       gundirectionarrow.setLocalTranslation(temdir2);
	}


}
